﻿using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using YooAsset;

public class PatchWindow : MonoBehaviour
{
    /// <summary>
    /// 对话框封装类
    /// </summary>
    private class MessageBox
    {
        private GameObject _cloneObject;
        private Text _content;
        private Button _btnOK;
        private System.Action _clickOK;

        public bool ActiveSelf
        {
            get { return _cloneObject.activeSelf; }
        }

        public void Create(GameObject cloneObject)
        {
            _cloneObject = cloneObject;
            _content = cloneObject.transform.Find("txt_content").GetComponent<Text>();
            _btnOK = cloneObject.transform.Find("btn_ok").GetComponent<Button>();
            _btnOK.onClick.AddListener(OnClickYes);
        }

        public void Show(string content, System.Action clickOK)
        {
            _content.text = content;
            _clickOK = clickOK;
            _cloneObject.SetActive(true);
            _cloneObject.transform.SetAsLastSibling();
        }

        public void Hide()
        {
            _content.text = string.Empty;
            _clickOK = null;
            _cloneObject.SetActive(false);
        }

        private void OnClickYes()
        {
            _clickOK?.Invoke();
            Hide();
        }
    }

    private readonly List<MessageBox> _msgBoxList = new List<MessageBox>();

    // UGUI相关
    private GameObject _messageBoxObj;

    public TextMeshProUGUI _statusTxt;
    public TextMeshProUGUI _perTxt;
    public Image _imgBar;

    private void OnEnable()
    {
        SubscribeEvents();
    }

    private void OnDisable()
    {
        UnsubscribeEvents();
    }

    private void SubscribeEvents()
    {
        GameEvent.OnPatchStepsChange += OnPatchStepsChange;
        GameEvent.OnFoundUpdateFiles += OnFoundUpdateFiles;
        GameEvent.OnDownloadUpdate += OnDownloadUpdate;
        GameEvent.OnPackageVersionRequestFailed += OnPackageVersionRequestFailed;
        GameEvent.OnPackageManifestUpdateFailed += OnPackageManifestUpdateFailed;
        GameEvent.OnWebFileDownloadFailed += OnWebFileDownloadFailed;
        GameEvent.OnInitializeFailed += OnInitializeFailed;
    }

    private void UnsubscribeEvents()
    {
        GameEvent.OnPatchStepsChange -= OnPatchStepsChange;
        GameEvent.OnFoundUpdateFiles -= OnFoundUpdateFiles;
        GameEvent.OnDownloadUpdate -= OnDownloadUpdate;
        GameEvent.OnPackageVersionRequestFailed -= OnPackageVersionRequestFailed;
        GameEvent.OnPackageManifestUpdateFailed -= OnPackageManifestUpdateFailed;
        GameEvent.OnWebFileDownloadFailed -= OnWebFileDownloadFailed;
        GameEvent.OnInitializeFailed -= OnInitializeFailed;
    }

    private void OnPatchStepsChange(PatchStepDefine step)
    {
        switch (step)
        {
            case PatchStepDefine.Initialize:
                _perTxt.gameObject.SetActive(false);
                _statusTxt.text = "正在初始化资源包";
                _imgBar.fillAmount = 0;
                break;
            case PatchStepDefine.Version:
                _perTxt.gameObject.SetActive(false);
                _statusTxt.text = "正在请求资源版本";
                _imgBar.fillAmount = 0;
                break;
            case PatchStepDefine.Manifest:
                _perTxt.gameObject.SetActive(false);
                _statusTxt.text = "正在更新Manifest";
                _imgBar.fillAmount = 0;
                break;
            case PatchStepDefine.CreateDownloader:
                _perTxt.gameObject.SetActive(false);
                _statusTxt.text = "正在创建资源下载器";
                _imgBar.fillAmount = 0;
                break;
            case PatchStepDefine.Download:
                _perTxt.gameObject.SetActive(true);
                _statusTxt.text = "更新文件";
                break;
            case PatchStepDefine.DownloadOver:
                _perTxt.gameObject.SetActive(true);
                _statusTxt.text = "更新完成";
                _imgBar.fillAmount = 1;
                GameEvent.SendDownloadOver();
                break;
            case PatchStepDefine.ClearCache:
                _perTxt.gameObject.SetActive(false);
                _statusTxt.text = "清理未使用的缓存文件";
                _imgBar.fillAmount = 1;
                break;
            case PatchStepDefine.StartGame:
                _perTxt.gameObject.SetActive(false);
                _statusTxt.text = "开始游戏";
                _imgBar.fillAmount = 1;
                break;
            default:
                break;
        }
    }

    private void OnFoundUpdateFiles(int totalCount, long totalSizeBytes)
    {
        Action callback = () => { GameEvent.SendTryDownload(); };
        float sizeMB = totalSizeBytes / 1048576f;
        sizeMB = Mathf.Clamp(sizeMB, 0.1f, float.MaxValue);
        string totalSizeMB = sizeMB.ToString("f1");
        ShowMessageBox($"Found update patch files, Total count {totalCount} Total szie {totalSizeMB}MB", callback);
    }

    private void OnDownloadUpdate(DownloadUpdateData updateData)
    {
        var per = (float)updateData.CurrentDownloadCount / updateData.TotalDownloadCount;
        _imgBar.fillAmount = per;
        string currentSizeMB = (updateData.CurrentDownloadBytes / 1048576f).ToString("f1");
        string totalSizeMB = (updateData.TotalDownloadBytes / 1048576f).ToString("f1");
        var tip =
            $"{updateData.CurrentDownloadCount}/{updateData.TotalDownloadCount} {currentSizeMB}MB/{totalSizeMB}MB";
        _perTxt.text = tip;
    }

    private void OnPackageVersionRequestFailed()
    {
        Action callback = () => { GameEvent.SendTryPackageVersion(); };
        ShowMessageBox($"Failed to request package version, please check the network status.", callback);
    }

    private void OnPackageManifestUpdateFailed()
    {
        Action callback = () => { GameEvent.SendTryPackageManifest(); };
        ShowMessageBox($"Failed to update patch manifest, please check the network status.", callback);
    }

    private void OnWebFileDownloadFailed(DownloadErrorData errorData)
    {
        Action callback = () => { GameEvent.SendTryDownload(); };
        ShowMessageBox($"Failed to download file : {errorData.FileName}", callback);
    }

    private void OnInitializeFailed()
    {
        Action callback = () => { GameEvent.SendStartInitialize(); };
        ShowMessageBox($"Failed to initialize package !", callback);
    }

    /// <summary>
    /// 显示对话框
    /// </summary>
    private void ShowMessageBox(string content, Action ok)
    {
        // 尝试获取一个可用的对话框
        MessageBox msgBox = null;
        for (int i = 0; i < _msgBoxList.Count; i++)
        {
            var item = _msgBoxList[i];
            if (item.ActiveSelf == false)
            {
                msgBox = item;
                break;
            }
        }

        // 如果没有可用的对话框，则创建一个新的对话框
        if (msgBox == null)
        {
            msgBox = new MessageBox();
            var cloneObject = GameObject.Instantiate(_messageBoxObj, _messageBoxObj.transform.parent);
            msgBox.Create(cloneObject);
            _msgBoxList.Add(msgBox);
        }

        // 显示对话框
        msgBox.Show(content, ok);
    }
}